package com.bll.tsdoa.utils;

import com.bll.tsdoa.entity.Cutting;
import com.bll.tsdoa.entity.Part;
import com.bll.tsdoa.entity.Pattern;
import com.bll.tsdoa.entity.Raw;
import com.bll.tsdoa.mapper.CuttingDao;
import com.bll.tsdoa.mapper.PartDao;
import com.bll.tsdoa.mapper.PatternDao;
import com.bll.tsdoa.mapper.RawDao;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 根据传入的零件和原料生成排样方案
 *
 * @author bll
 * @version 1.0
 * @date 2025/2/26 21:09
 */
@Component
@Slf4j
@Getter
public class GaUtils {

    int Population_Size = 20;
    double Cross_rate = 1;
    double MUTATION_RATE = 0.001;
    @Resource
    private PartDao partDao;
    @Resource
    private RawDao rawDao;
    // 添加bitLength存储
    private int bitLength;
    private double maxRawLength;
    private Double minPartLength;
    private List<Part> partList;
    private List<Raw> rawList;
    @Autowired
    private CuttingDao cuttingDao;
    @Resource
    private DefaultIdentifierGenerator defaultIdentifierGenerator;
    @Resource
    private PatternDao patternDao;
    @Resource
    private CommonUtils commonUtils;

    // 初始化时计算bitLength
    public void init() {
        this.partList = partDao.selectList(null);
        this.rawList = rawDao.selectList(null);
        this.maxRawLength = commonUtils.getMaxRawLength(rawList);
        this.minPartLength = commonUtils.getMinPartLength(partList);
        this.bitLength = getCount(maxRawLength, minPartLength);
    }


    public List<int[]> initPolulation() {
        init();
        // ✅ 添加非空校验
        if (partDao == null || rawDao == null) {
            throw new IllegalStateException("DAO未注入");
        }

        List<Part> partList = partDao.selectList(null);
        List<Raw> rawList = rawDao.selectList(null);
//        Double maxRawLength = getMaxRawLength(rawList);
//
//        Double minPartLength = getMinPartLength(partList);
//        int bitLength = getCount(maxRawLength, minPartLength);
//        System.out.println("零件最小长度: " + minPartLength);
//        System.out.println("原料最大长度: " + maxRawLength);

//        System.out.println("最少需要二进制位数: " + bitLength);

        List<int[]> arrayList = new ArrayList<>();
        for (int i = 0; i < Population_Size; i++) {
            Raw randomRaw = getRandomRaw(rawList);
            int[] gene = getRandomGene(randomRaw, partList);

            int[] chromosome = encode(randomRaw.getId(), gene, bitLength, 1);
//            System.out.println("加密的染色体: " + Arrays.toString(chromosome));
            int[] decode = decode(chromosome, bitLength);
//            System.out.println("解密的染色体: " + Arrays.toString(decode));
            double fitness = fitness(decode);
//            System.out.println("适应度为: " + fitness);
            arrayList.add(chromosome);
        }
        return arrayList;
    }

    public Integer getCount(Double maxRawLength, Double minPartLength) {

        // 1. 校验数据有效性
        if (maxRawLength == null || minPartLength == null) {
            throw new IllegalArgumentException("数据不完整：原料或零件长度为 null");
        }
        if (minPartLength <= 0) {
            throw new IllegalArgumentException("最小零件长度必须 > 0");
        }

        // 2. 计算一根原料能切割的零件数量（向下取整）
        int count = (int) Math.floor(maxRawLength / minPartLength);
        if (count < 0) {
            throw new ArithmeticException("切割数量不能为负数");
        }

        // 3. 计算最少二进制位数
        int bitLength;
        if (count == 0) {
            bitLength = 1; // 0 的二进制为 "0"，占 1 位
        } else {
            // 方法一：直接计算二进制字符串长度
            String binaryString = Integer.toBinaryString(count);
            bitLength = binaryString.length();

            // 方法二：位运算（推荐，避免字符串转换）
            // bitLength = Integer.SIZE - Integer.numberOfLeadingZeros(count);
        }
        return bitLength;
    }


    private int[] encode(int rawId, int[] partNum, int bitLength, int Num) {
        // 参数校验
        if (partNum == null) {
            throw new IllegalArgumentException("partNum must not be null");
        }
        if (bitLength <= 0) {
//            throw new IllegalArgumentException("bitLength must be positive");
            log.error("bitLength must be positive:{}", bitLength);
        }
        if (rawId <= 0) { // 假设数据库ID从1开始
            throw new IllegalArgumentException("Raw ID必须大于0");
        }

        // 转换各部分为二进制数组
        int[] rawIdBinary = convertToBinary(rawId, 10);
        int[] numBinary = convertToBinary(Num, 10);

        // 处理partNum数组中的每个元素
        int partNumBits = bitLength;
        List<int[]> partNumBinaries = new ArrayList<>();
        for (int num : partNum) {
            partNumBinaries.add(convertToBinary(num, partNumBits));
        }

        // 计算总长度并初始化结果数组
        int totalLength = rawIdBinary.length + (partNum.length * partNumBits) + numBinary.length;
        int[] result = new int[totalLength];
        int index = 0;

        // 拼接rawId
        System.arraycopy(rawIdBinary, 0, result, index, rawIdBinary.length);
        index += rawIdBinary.length;

        // 拼接partNum的各个部分
        for (int[] partBinary : partNumBinaries) {
            System.arraycopy(partBinary, 0, result, index, partBinary.length);
            index += partBinary.length;
        }

        // 拼接Num
        System.arraycopy(numBinary, 0, result, index, numBinary.length);

        return result;
    }

    private int[] convertToBinary(int value, int bits) {
        int maskedValue = value & ((1 << bits) - 1);
        int[] binaryArray = new int[bits];
        for (int i = 0; i < bits; i++) {
            binaryArray[i] = (maskedValue >> (bits - 1 - i)) & 1;
        }
        return binaryArray;
    }

    public Raw getRandomRaw(List<Raw> rawList) {
        if (rawList == null || rawList.isEmpty()) {
            throw new IllegalArgumentException("原料列表不能为空");
        }

        // 生成随机索引
        Random random = new Random();
        int randomIndex = random.nextInt(rawList.size());

        // 返回随机选中的原料
        return rawList.get(randomIndex);
    }

    public int[] getRandomGene(Raw randomRaw, List<Part> partList) {
        // 参数校验
        if (randomRaw == null || partList == null) {
            throw new IllegalArgumentException("参数不能为 null");
        }
        for (Part part : partList) {
            if (part == null) {
                throw new IllegalArgumentException("partList 包含 null 元素");
            }
        }
        Double rawLength = randomRaw.getLength();
        if (rawLength == null || rawLength <= 0) {
            return new int[partList.size()]; // 返回全零数组
        }

        int[] gene = new int[partList.size()];       // 结果数组，记录每个零件切割次数
        int[] remainingNums = new int[partList.size()]; // 各零件剩余可用数量
        for (int i = 0; i < partList.size(); i++) {
            remainingNums[i] = partList.get(i).getNum();
        }
        double remainingRawLength = rawLength; // 原料剩余长度
        Random random = new Random();

        // 循环切割，直到无法继续
        while (true) {
            List<Integer> candidates = new ArrayList<>();
            // 收集可切割的零件索引
            for (int i = 0; i < partList.size(); i++) {
                Part part = partList.get(i);
                Double partLength = part.getLength();
                // 忽略无效零件（长度 <=0 或 null）
                if (partLength == null || partLength <= 0) {
                    continue;
                }
                // 检查剩余数量和原料长度
                if (remainingNums[i] > 0 && partLength <= remainingRawLength) {
                    candidates.add(i);
                }
            }
            if (candidates.isEmpty()) {
                break; // 无候选零件，终止切割
            }
            // 随机选择一个候选零件
            int selectedIndex = candidates.get(random.nextInt(candidates.size()));
            gene[selectedIndex]++;            // 记录切割次数
            remainingNums[selectedIndex]--;   // 减少该零件可用数量
            remainingRawLength -= partList.get(selectedIndex).getLength(); // 减少原料长度
        }

        return gene;
    }

    /*public double fitness(Raw raw, List<Part> partList, int[] partNum) {
        // 参数有效性校验
        if (raw == null || raw.getLength() <= 0) {
            throw new IllegalArgumentException("原料数据无效");
        }
        if (partList == null || partList.isEmpty()) {
            return 0.0; // 没有零件可切割，适应度为0
        }
        if (partNum == null || partList.size() != partNum.length) {
            throw new IllegalArgumentException("零件数量数组与零件列表长度不匹配");
        }

        // 计算总零件长度
        double totalPartsLength = 0.0;
        for (int i = 0; i < partList.size(); i++) {
            Part part = partList.get(i);
            if (part == null || part.getLength() == null) {
                continue; // 跳过无效零件
            }
            totalPartsLength += part.getLength() * partNum[i];
        }

        // 获取原料长度
        double rawLength = raw.getLength();

        // 计算适应度（比率）
        double fitness = totalPartsLength / rawLength;

        // 添加合理性约束（比率不应超过1）
//        return Math.min(fitness, 1.0);
        if (fitness >= 1) {
            System.out.println("fitness计算错误" + fitness);
        }
        return fitness;
    }*/

    public double fitness(int[] decode) {
        // 参数校验
        if (decode == null || decode.length < 2) {
            throw new IllegalArgumentException("Invalid decode array");
        }

        // 提取rawId
        int rawId = decode[0];
        if (rawId == 0) {
            log.error("rawid==0,decode为:{}", Arrays.toString(decode));
        }
        // 提取partNum,解码之后的零件个数解（排除最后一个元素，假设最后一个是num）
        int[] partNum = Arrays.copyOfRange(decode, 1, decode.length - 1);
        // 提取num（可能不使用）
        int num = decode[decode.length - 1];

        // 查询原材料长度
        Raw raw = rawDao.selectById(rawId);
        if (raw == null || raw.getLength() == null || raw.getLength() <= 0) {
            log.error("Invalid raw material ID: " + rawId);
//            throw new IllegalArgumentException("Invalid raw material ID: " + rawId);
        }
        double rawLength = raw.getLength();

        // 查询所有零件
        List<Part> parts = partDao.selectList(null);

        if (parts.size() != partNum.length) {
//            throw new IllegalArgumentException("Part numbers do not match parts list");
            log.error("parts.size():{},partNum.length:{}", parts.size(), partNum.length);
        }


        // 计算总零件长度
        double totalPartsLength = 0.0;
        for (int i = 0; i < parts.size(); i++) {
            Part part = parts.get(i);
            if (part == null || part.getLength() == null) {
                continue; // 跳过无效零件或记录错误
            }
            totalPartsLength += part.getLength() * partNum[i];
        }

        // 计算适应度
        double fitness = totalPartsLength / rawLength;
        return fitness;
    }

    public int[] decode(int[] encoded, int bitLength) {
        // 参数校验
        if (encoded == null) {
            throw new IllegalArgumentException("encoded array must not be null");
        }
        if (bitLength <= 0) {
            throw new IllegalArgumentException("bitLength must be positive");
        }
        int totalBits = encoded.length;
        if (totalBits < 20) {
            throw new IllegalArgumentException("encoded array is too short");
        }
        int remainingBits = totalBits - 20; // rawId(10位) + Num(10位)
        if (remainingBits % bitLength != 0) {
            throw new IllegalArgumentException("encoded array length does not match bitLength");
        }
        int numParts = remainingBits / bitLength;

        // 1. 解码 rawId（前10位）
        int[] rawIdBinary = Arrays.copyOfRange(encoded, 0, 10);

        int rawId = convertFromBinary(rawIdBinary);
//        System.out.println("Debug - rawId二进制: " + Arrays.toString(rawIdBinary) + " → " + rawId); // 调试输出

        // 2. 解码 partNum 数组
        int[] partNum = new int[numParts];
        int startIndex = 10;
        for (int i = 0; i < numParts; i++) {
            int endIndex = startIndex + bitLength;
            int[] partBinary = Arrays.copyOfRange(encoded, startIndex, endIndex);
            partNum[i] = convertFromBinary(partBinary);
            startIndex = endIndex;
        }

        // 3. 解码 Num（最后10位）
        int[] numBinary = Arrays.copyOfRange(encoded, encoded.length - 10, encoded.length);
        int num = convertFromBinary(numBinary);

        // 组合结果数组：[rawId, partNum, ..., partNum[N-1], num]
        int[] result = new int[1 + numParts + 1];
        result[0] = rawId;
        System.arraycopy(partNum, 0, result, 1, numParts);
        result[result.length - 1] = num;

        return result;
    }

    private int convertFromBinary(int[] binaryArray) {
        int value = 0;
        for (int bit : binaryArray) {
            value = (value << 1) | (bit & 1); // 确保每位是0或1
        }
        return value;
    }

/*    public Double getMaxRawLength(List<Raw> rawList) {
        Double maxRawLength = rawList.stream().map(Raw::getLength)       // 提取每个对象的 length
                .filter(Objects::nonNull)  // 过滤掉 null 值（确保比较安全）
                .max(Double::compare)      // 找到最大值
                .orElse(null);             // 处理空情况，返回 null 或默认值
        return maxRawLength;
    }*/

/*    public Double getMinPartLength(List<Part> partList) {
        Double minLength = partList.stream().map(Part::getLength)       // 提取每个对象的 length
                .filter(Objects::nonNull)   // 过滤掉 null 值（确保比较安全）
                .min(Double::compare)       // 找到最小值
                .orElse(null);              // 处理空情况，返回 null 或默认值
        return minLength;
    }*/

    private List<Double> buildRouletteWheel(List<Double> fitnessValues, double totalFitness) {
        List<Double> wheel = new ArrayList<>();
        double cumulative = 0.0;

        for (Double fitness : fitnessValues) {
            // 显式处理负适应度
            double adjustedFitness = Math.max(fitness, 0.0);
            double probability = (totalFitness > 0) ? adjustedFitness / totalFitness : 1.0 / fitnessValues.size();
            cumulative += probability;
            wheel.add(cumulative);
        }

        // 归一化处理（防止累积和因精度问题不等于1）
        if (!wheel.isEmpty()) {
            double last = wheel.get(wheel.size() - 1);
            if (last > 0) {
                for (int i = 0; i < wheel.size(); i++) {
                    wheel.set(i, wheel.get(i) / last);
                }
            }
        }

        return wheel;
    }

    public List<int[]> selectCopy(List<int[]> population) {
        List<int[]> validPopulation = new ArrayList<>();
        List<Double> fitnessValues = new ArrayList<>();

        for (int[] chromo : population) {
            try {
                // 关键修正：先解码再计算适应度
                int[] decoded = decode(chromo, this.bitLength);
                double fit = fitness(decoded); // 传入解码后的参数数组

                validPopulation.add(chromo);    // 保留原始编码染色体
                fitnessValues.add(fit);
            } catch (IllegalArgumentException e) {
                log.error("过滤无效染色体: " + Arrays.toString(chromo));
            }
        }

        // 计算轮盘赌
        double totalFitness = fitnessValues.stream().mapToDouble(d -> d).sum();
        List<Double> wheel = buildRouletteWheel(fitnessValues, totalFitness);

        // 生成阶段
        return generateNewPopulation(validPopulation, wheel);
    }

    private List<int[]> generateNewPopulation(List<int[]> validPopulation, List<Double> wheel) {
        List<int[]> newPopulation = new ArrayList<>();
        Random rand = new Random();

        for (int i = 0; i < validPopulation.size(); i++) {
            // 使用轮盘赌选择索引
            int selectedIndex = selectByRoulette(wheel, rand);

            // 获取被选中的染色体
            int[] selected = validPopulation.get(selectedIndex);

            try {
                // 验证染色体有效性
                this.fitness(decode(selected, this.bitLength));
                newPopulation.add(Arrays.copyOf(selected, selected.length));
            } catch (IllegalArgumentException e) {
                // 降级处理：随机选择一个有效个体
                int backupIndex = rand.nextInt(validPopulation.size());
                newPopulation.add(Arrays.copyOf(validPopulation.get(backupIndex), validPopulation.get(backupIndex).length));
            }
        }

        return newPopulation;
    }

    private int[] getRandomValid(List<int[]> validPopulation, Random rand) {
        return validPopulation.get(rand.nextInt(validPopulation.size())).clone();
    }

    private int selectByRoulette(List<Double> wheel, Random rand) {
        // 生成随机指针（范围 [0.0, 1.0) ）
        double pointer = rand.nextDouble();

        // 二分查找确定选择索引
        int index = Collections.binarySearch(wheel, pointer);

        // 处理二分查找的返回值：
        // - 正值: 直接命中
        // - 负值: 转换为插入点 (-(insertion point) - 1)
        index = (index >= 0) ? index : -(index + 1);

        // 确保索引不越界（处理pointer接近1.0的边界情况）
        return Math.min(index, wheel.size() - 1);
    }

    public Object[] getSortedFitnessArray(List<int[]> population) {
        // 参数校验
        if (population == null || population.isEmpty()) {
            throw new IllegalArgumentException("种群不能为空");
        }

        // 获取解码所需的bitLength（假设已在类中初始化）
        if (this.bitLength <= 0) {
            throw new IllegalStateException("bitLength未正确初始化");
        }

        // 使用流处理进行解码、适应度计算和排序
        return population.stream().map(chromo -> {
                    try {
                        // 解码染色体（二进制数组 → 实际参数数组）
                        int[] decoded = decode(chromo, this.bitLength);
                        // 计算适应度（使用解码后的参数数组）
                        return fitness(decoded);
                    } catch (IllegalArgumentException e) {
                        // 无效染色体标记为负无穷，排序时自动沉底
                        return Double.NEGATIVE_INFINITY;
                    }
                }).sorted(new Comparator<Double>() {
                    @Override
                    public int compare(Double o1, Double o2) {
                        return Double.compare(o2, o1);
                    }
                }) // 降序排序
                .toArray();
    }

    public List<int[]> cross(List<int[]> population, int length) {
        List<int[]> newPopulation = new ArrayList<>();
        Random rand = new Random();

        // 1. 按适应度排序种群
        List<int[]> sortedPopulation = population.stream().sorted((a, b) -> Double.compare(fitness(decode(b, bitLength)), fitness(decode(a, bitLength)))) // 降序排序
                .collect(Collectors.toList());

        // 2. 两两交叉（处理奇数情况）
        for (int i = 0; i < sortedPopulation.size() - 1; i += 2) {
            int[] parent1 = sortedPopulation.get(i);
            int[] parent2 = sortedPopulation.get(i + 1);

            // 3. 按交叉率决定是否执行交叉
            if (rand.nextDouble() > Cross_rate) {
                newPopulation.add(parent1.clone());
                newPopulation.add(parent2.clone());
                continue;
            }

            // 4. 执行基因交叉（仅交换partNum部分）
            int[] child1 = parent1.clone();
            int[] child2 = parent2.clone();

            // 零件数量起始位置（跳过rawId和最后的num）
            int partStart = 1;
            int partEnd = parent1.length - 1;

            // 生成掩码（例如bitLength=1 → 0b1）
            int mask = (1 << length) - 1;

            // 5. 交换每个零件的低位bitLength位
            for (int j = partStart; j < partEnd; j++) {
                // 获取父代基因位
                int p1Bits = parent1[j] & mask;
                int p2Bits = parent2[j] & mask;

                // 执行交叉交换
                child1[j] = (parent1[j] & ~mask) | p2Bits;
                child2[j] = (parent2[j] & ~mask) | p1Bits;
            }

            // 6. 验证适应度并决定是否保留子代
            handleOffspring(newPopulation, parent1, parent2, child1, child2);
        }

        // 处理奇数数量种群的最后一个个体
        if (sortedPopulation.size() % 2 != 0) {
            newPopulation.add(sortedPopulation.get(sortedPopulation.size() - 1).clone());
        }

        return newPopulation;
    }

    /*    private void handleOffspring(List<int[]> population, int[] parent1, int[] parent2, int[] child1, int[] child2) {
            try {
                double fitness1 = fitness(decode(child1, bitLength));
                double fitness2 = fitness(decode(child2, bitLength));

                // 子代有效时保留
                if (fitness1 <= 1.0 && fitness2 <= 1.0) {
                    population.add(child1);
                    population.add(child2);
                }
                // 子代无效时恢复父代
                else {
                    population.add(parent1.clone());
                    population.add(parent2.clone());
                }
            } catch (Exception e) {
                // 出现异常时恢复父代
                population.add(parent1.clone());
                population.add(parent2.clone());
            }
        }*/
    private void handleOffspring(List<int[]> population, int[] parent1, int[] parent2, int[] child1, int[] child2) {

        double fitness1 = fitness(decode(child1, bitLength));
        double fitness2 = fitness(decode(child2, bitLength));

        try {
            // 子代有效时保留
            if (fitness1 <= 1.0) {
                population.add(child1);
            } else {        // 子代无效时恢复父代
                population.add(parent1.clone());
            }
            // 子代有效时保留
            if (fitness2 <= 1.0) {
                population.add(child2);
            } else {        // 子代无效时恢复父代
                population.add(parent2.clone());
            }
        } catch (Exception e) {
//            throw new RuntimeException(e);
            log.error("GaUtils.handleOffspring:{}", e.getMessage());
            // 出现异常时恢复父代
            population.add(parent1.clone());
            population.add(parent2.clone());
        }
    }


    public int[] mutate(List<int[]> population, int id) {
        // 参数校验
        if (population == null || population.isEmpty()) {
            throw new IllegalArgumentException("种群不能为空");
        }
        if (id < 0 || id >= population.size()) {
            throw new IllegalArgumentException("无效的染色体ID");
        }

        int[] original = population.get(id).clone(); // 原始染色体
        int[] mutated = original.clone();           // 变异后的染色体

        // 1. 确定染色体结构（首尾各10位，中间为解）
        int headTailBits = 10;
        int totalBits = mutated.length;
        int middleStart = headTailBits;              // 中间解起始位置
        int middleEnd = totalBits - headTailBits - 1; // 中间解结束位置
        int middleBits = middleEnd - middleStart + 1;

        // 若中间无解或bitLength未定义，直接返回
        if (middleBits <= 0) return original;

        // 2. 计算中间解的bitLength（假设中间部分为整数个解）
//        int bitLength = middleBits / ((mutated.length - 20) / 10); // 示例逻辑，需根据实际调整
        int numMiddleGenes = middleBits / bitLength;               // 中间解数量

        // 3. 计算总基因位数（中间解的二进制位数总和）
//        int totalGeneBits = numMiddleGenes * bitLength;
        int totalGeneBits = original.length;

        // 4. 计算总突变次数（基因位数 × 突变率，向上取整）
        int totalMutations = (int) Math.ceil(totalGeneBits * MUTATION_RATE);
        if (totalMutations < 1) return original;

        // 5. 均匀分配突变次数到各中间解
        int[] mutationsPerGene = distributeMutations(numMiddleGenes, totalMutations);

        // 6. 对每个中间解的低位进行变异
        Random rand = new Random();
        for (int geneIdx = 0; geneIdx < numMiddleGenes; geneIdx++) {
            int mutations = mutationsPerGene[geneIdx];
            if (mutations <= 0) continue;

            // 计算当前解的二进制范围（例如：解3占bitLength位）
            int geneStart = middleStart + geneIdx * bitLength;
            int geneEnd = geneStart + bitLength - 1;

            // 确定低位区域（后1/3位，向上取整）
            int lowBits = (int) Math.ceil(bitLength / 3.0);
            lowBits = Math.max(1, lowBits); // 至少1位
            int lowStart = geneStart + (bitLength - lowBits);

            // 随机翻转低位
            for (int i = 0; i < mutations; i++) {
                int bitPos = lowStart + rand.nextInt(lowBits);
                if (bitPos > geneEnd) bitPos = geneEnd; // 边界保护
                mutated[bitPos] ^= 1; // 翻转位
            }
        }
        // 7. 检查适应度和库存是否合法
        int[] mutatedDecoded = decode(mutated, bitLength);
        boolean isFeasible = checkFeasibility(mutatedDecoded) && fitness(mutatedDecoded) <= 1.0;

        return isFeasible ? mutated : original;
    }

    // 均匀分配突变次数（例如：7次分到3个解 → [3,2,2]）
    private int[] distributeMutations(int numGenes, int total) {
        int[] dist = new int[numGenes];
        int base = total / numGenes;
        int remainder = total % numGenes;
        Arrays.fill(dist, base);
        for (int i = 0; i < remainder; i++) dist[i]++;
        return dist;
    }

    private boolean checkFeasibility(int[] decoded) {
        if (decoded == null || decoded.length < 2) return false;

        int[] partCuts = Arrays.copyOfRange(decoded, 1, decoded.length - 1);
        List<Part> parts = partDao.selectList(null);

        if (partCuts.length != parts.size()) return false;

        for (int i = 0; i < parts.size(); i++) {
            Part part = parts.get(i);
            if (part.getNum() < partCuts[i]) {
                return false; // 库存不足
            }
        }
        return true;
    }

    public int[] simulatedAnnealing(List<int[]> population) {
        // 参数校验
        if (population == null || population.isEmpty()) {
            throw new IllegalArgumentException("种群不能为空");
        }

        // 1. 计算所有染色体适应度并记录原始索引
        List<Double> fitnessList = new ArrayList<>(population.size());
        for (int[] chromo : population) {
            fitnessList.add(fitness(decode(chromo, this.bitLength)));
        }

        // 2. 按适应度从低到高排序（保留原始索引）
        List<Integer> sortedIndices = IntStream.range(0, population.size()).boxed().sorted(Comparator.comparingDouble(fitnessList::get)).collect(Collectors.toList());

        // 3. 初始化退火参数
        double initialTemp = 1000.0;
        double coolingRate = 0.95;
        double currentTemp = initialTemp;

        // 4. 初始化当前解和最优解（从最高适应度开始）
        int[] bestSolution = population.get(sortedIndices.get(sortedIndices.size() - 1)).clone(); // 初始化为最高适应度解
        double bestEnergy = fitnessList.get(sortedIndices.get(sortedIndices.size() - 1));

        // 5. 遍历每个染色体（从低到高）
        for (int idx : sortedIndices) {
            int[] currentSolution = population.get(idx).clone();
            double currentEnergy = fitnessList.get(idx);

            // 5.1 生成新解（变异当前染色体）
            List<int[]> tempPop = Collections.singletonList(currentSolution);
            int[] newSolution = mutate(tempPop, 0);
            int[] newDecoded = decode(newSolution, this.bitLength);
            double newEnergy = fitness(newDecoded);

            // 新增：检查新解的可行性
            if (!checkFeasibility(newDecoded)) {
                newEnergy = Double.NEGATIVE_INFINITY; // 标记为不可接受
            }

            // 5.2 Metropolis准则
            if (acceptNewSolution(newEnergy - currentEnergy, currentTemp)) {
                currentSolution = newSolution.clone();
                currentEnergy = newEnergy;
            }

            // 5.3 更新全局最优解
            if (currentEnergy > bestEnergy) {
                bestSolution = currentSolution.clone();
                bestEnergy = currentEnergy;
            }

            // 5.4 降温（每个个体独立降温）
            currentTemp *= coolingRate;
        }

        return bestSolution;
    }

    /**
     * 修正后的接受准则（处理数值稳定性）
     */

    private boolean acceptNewSolution(double deltaEnergy, double temperature) {
        if (deltaEnergy > 0) return true;
        if (temperature < 1e-6) return false; // 避免除以接近0的温度

        // 数值稳定处理：限制指数范围
        double exponent = Math.max(-100, deltaEnergy / temperature); // 防止下溢
        return Math.exp(exponent) > new Random().nextDouble();
    }

    @Transactional
    public void finish(int[] chromo) {
        // 1. 解码染色体

        int[] decode = decode(chromo, bitLength);
        int rawId = decode[0];
        int[] partCuts = Arrays.copyOfRange(decode, 1, decode.length - 1); // 去掉首尾

        // 2. 查询原料有效性
        Raw raw = rawDao.selectById(rawId);
        if (raw == null) {
            throw new RuntimeException("原料ID不存在: " + rawId);
        }

        // 3. 获取所有零件当前库存
        List<Part> parts = this.partList;

        if (parts.size() != partCuts.length) {
            throw new RuntimeException("染色体零件数量与数据库不匹配");
        }

        // 4. 计算最小所需原料块数
        int minBlocks = Integer.MAX_VALUE;
        for (int i = 0; i < parts.size(); i++) {
            Part part = parts.get(i);
            int cutCount = partCuts[i];

            if (cutCount == 0) continue; // 忽略不切割的零件

            int remaining = part.getNum();
            if (remaining <= 0) {
                log.error("零件{}库存不足:,还剩{}件,需要{}件", part.getId(), remaining, cutCount);
            }

            // 计算该零件允许的最大切割批次
            int possibleBlocks = remaining / cutCount;
            minBlocks = Math.min(minBlocks, possibleBlocks);
        }

        if (minBlocks == Integer.MAX_VALUE) {
            throw new RuntimeException("所有零件切割次数均为0，无效方案");
        }

        // 5. 更新零件库存,并记录生产方案到数据库（可选）
        long cuttingId = defaultIdentifierGenerator.nextId();
        Pattern pattern = getPattern(cuttingId, rawId, minBlocks);


//        ArrayList<Cutting> cuttingList = new ArrayList<>();
        for (int i = 0; i < parts.size(); i++) {
            Part part = parts.get(i);
            int cutCount = partCuts[i];

            if (cutCount == 0) continue;

            int consumed = cutCount * minBlocks;
            Cutting cutting = getCutting(cuttingId, part, cutCount);

            if (part.getNum() < consumed) {
                throw new RuntimeException("零件库存计算异常: " + part.getId());
            }

            part.setNum(part.getNum() - consumed);
            partDao.updateById(part); // 假设使用MyBatis-Plus的更新方法
        }
//        pattern.setCuttingList(cuttingList);

        // productionService.record(rawId, minBlocks, partCuts);
    }

    private Pattern getPattern(long cuttingId, int rawId, int minBlocks) {
//        System.out.println("Cutting ID: " + cuttingId);
        Pattern pattern = new Pattern();
        pattern.setCuttingId(cuttingId);
        pattern.setRawId(rawId);
        pattern.setCastNum(minBlocks);
//        LambdaQueryWrapper<Raw> eq = new LambdaQueryWrapper<Raw>().select(Raw::getLength).eq(Raw::getId, rawId);
        Raw raw = rawDao.selectById(rawId);
        pattern.setRawLength(raw.getLength());
        patternDao.insert(pattern);
        return pattern;
    }

    private Cutting getCutting(long cuttingId, Part part, int consumed) {
        //插入一个临时零件
//        System.out.println("Cutting ID: " + cuttingId);
        Cutting cutting = new Cutting().
                setCuttingId(cuttingId).
                setPartId(part.getId()).
                setPartLength(part.getLength()).
                setPartNum(consumed);
        cuttingDao.insert(cutting);
        return cutting;
    }
}

